package com.icoolkj.ms.common.security.aspect;

import com.icoolkj.ms.api.auth.bo.UserInfoInTokenBO;
import com.icoolkj.ms.api.rbac.feign.PermissionFeignClient;
import com.icoolkj.ms.common.core.enums.ResponseEnum;
import com.icoolkj.ms.common.core.exception.IcoolkjMSException;
import com.icoolkj.ms.common.core.response.ServerResponseEntity;
import com.icoolkj.ms.common.core.utils.SpringContextUtils;
import com.icoolkj.ms.common.security.AuthUserContext;
import com.icoolkj.ms.common.security.annotation.RequiresPermissions;
import com.icoolkj.ms.common.security.enums.Logical;
import com.icoolkj.ms.common.security.utils.AuthUtils;
import lombok.NoArgsConstructor;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;

/**
 * @author icoolkj
 * @version 1.0
 * @description 基于 spring aop 的注解鉴权
 * @createDate 2025/02/16 13:56
 */
@Aspect
@Component
@NoArgsConstructor
public class PreAuthorizeAspect {

    private static final Logger logger = LoggerFactory.getLogger(PreAuthorizeAspect.class);

    @Autowired
    private PermissionFeignClient permissionFeignClient;

    /*** 定义AOP签名 (切入所有使用鉴权注解的方法) ***/
    public static final String POINTCUT_SIGN = """
            @annotation(com.icoolkj.ms.common.security.annotation.RequiresPermissions)
            """;

    /*** 声明 AOP 签名 ***/
    @Pointcut(POINTCUT_SIGN)
    public void pointcut(){

    }

    /**
     * 环绕切入
     *
     * @param joinPoint 切面对象
     * @return 底层方法执行后的返回值
     * @throws Throwable 底层方法抛出的异常
     */
    @Around("pointcut()")
    public Object around(ProceedingJoinPoint joinPoint) {
        // 注解鉴权
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        try {
            checkMethodAnnotation(signature.getMethod());
            // 执行原有逻辑
            return joinPoint.proceed();
        } catch (Throwable e) {
            logger.error("权限验证失败，方法: {}", joinPoint.getSignature().getName(), e);
            return ServerResponseEntity.fail(ResponseEnum.UNAUTHORIZED);
        }
    }

    /*** 对一个Method对象进行注解检查 ***/
    public void checkMethodAnnotation(Method method)
    {
        // 校验 @RequiresLogin 注解
//        RequiresLogin requiresLogin = method.getAnnotation(RequiresLogin.class);
//        if (requiresLogin != null)
//        {
//            AuthUtil.checkLogin();
//        }

        // 校验 @RequiresRoles 注解
//        RequiresRoles requiresRoles = method.getAnnotation(RequiresRoles.class);
//        if (requiresRoles != null)
//        {
//            AuthUtil.checkRole(requiresRoles);
//        }

        // 校验 @RequiresPermissions 注解
        RequiresPermissions requiresPermissions = method.getAnnotation(RequiresPermissions.class);
        if (requiresPermissions != null) {
            ServerResponseEntity<Boolean> isAuthorized;
            UserInfoInTokenBO userInfoInTokenBO = AuthUserContext.get();
            if (requiresPermissions.logical() == Logical.AND) {
                isAuthorized = permissionFeignClient.checkPermiAnd(userInfoInTokenBO.getUserId(),
                        userInfoInTokenBO.getUserType(), requiresPermissions.value());
            } else {
                isAuthorized = permissionFeignClient.checkPermiOr(userInfoInTokenBO.getUserId(),
                        userInfoInTokenBO.getUserType(), requiresPermissions.value());
            }
            if (!isAuthorized.isSuccess() || !isAuthorized.getData()) {
                throw new IcoolkjMSException(ResponseEnum.UNAUTHORIZED);
            }
        }

    }



}
